package com.haoqizhe.kernel.mybatis.generator.plugins;

import com.haoqizhe.kernel.mybatis.generator.utils.JavaTypeEnum;
import com.haoqizhe.kernel.mybatis.generator.utils.AnnotationEnum;
import com.haoqizhe.kernel.mybatis.generator.utils.StringUtils;
import org.mybatis.generator.api.*;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.internal.util.StringUtility;

import java.util.*;

/**
 * mybatis generator lombok plugin
 *
 * @author haoqizhe.li
 * @date 2018/1/20
 */
public class ModelPlugin extends PluginAdapter {
    private Properties systemPro;

    private static final Set<AnnotationEnum> LOMBOK_ENUM = new LinkedHashSet<>();
    /**
     * 实体model 是否添加swagger API 注解
     **/
    private boolean addSwagger = false;
    /**
     * 实体model 实体添加 hibernate validate 数据校验注解
     **/
    private boolean addHibernateValidate = false;

    private boolean addRootClass = false;
    private String rootClass;
    private boolean addPkType = false;
    private boolean messageUseColumnName = false;
    /**
     * 生成代码作者
     **/
    private String author;

    public ModelPlugin() {
        systemPro = System.getProperties();

        LOMBOK_ENUM.add(AnnotationEnum.DATA);
        LOMBOK_ENUM.add(AnnotationEnum.All_ARGS_CONSTRUCTOR);
        LOMBOK_ENUM.add(AnnotationEnum.NO_ARGS_CONSTRUCTOR);
    }

    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        rootClass = properties.getProperty("rootClass");
        author = properties.getProperty("author", systemPro.getProperty("user.name"));

        String tempSwagger = properties.getProperty("addSwagger");
        String tempValidate = properties.getProperty("addHibernateValidate");
        String tempRootClass = properties.getProperty("addRootClass");
        String tempPkType = properties.getProperty("addPkType");
        String tempColumnName = properties.getProperty("messageUseColumnName");
        boolean checkSwagger = tempSwagger == null || "".equals(tempSwagger) ||
                (!"false".equals(tempSwagger) && !"true".equals(tempSwagger));
        boolean checkValidate = tempValidate == null || "".equals(tempValidate) ||
                (!"false".equals(tempValidate) && !"true".equals(tempValidate));
        boolean checkRootClass = tempRootClass == null || "".equals(tempRootClass) ||
                (!"false".equals(tempRootClass) && !"true".equals(tempRootClass));
        boolean checkPkType = tempPkType == null || "".equals(tempPkType) ||
                (!"false".equals(tempPkType) && !"true".equals(tempPkType));
        boolean checkColumnName = tempColumnName == null || "".equals(tempColumnName) ||
                (!"false".equals(tempColumnName) && !"true".equals(tempColumnName));

        addSwagger = checkSwagger ? false : Boolean.parseBoolean(tempSwagger);
        addHibernateValidate = checkValidate ? false : Boolean.parseBoolean(tempValidate);
        addRootClass = checkRootClass ? false : Boolean.parseBoolean(tempRootClass);
        addPkType = checkPkType ? false : Boolean.parseBoolean(tempPkType);
        messageUseColumnName = checkColumnName ? false : Boolean.parseBoolean(tempColumnName);

        if (addRootClass) {
            if (!StringUtility.stringHasValue(rootClass)) {
                throw new RuntimeException("isRootClass属性为true时，Mapper插件缺少必要的rootClass属性!");
            }
        }

        rootClass = properties.getProperty("rootClass");
    }

    /**
     * model自动生成时添加lombok注解
     *
     * @param topLevelClass
     * @param introspectedTable
     * @return
     */
    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {

        Object table = introspectedTable.getRemarks() == null || "".equals(introspectedTable.getRemarks()) ?
                introspectedTable.getFullyQualifiedTable() : introspectedTable.getRemarks();


        topLevelClass.addJavaDocLine(StringUtils.getComment(table + "实体", author));

        /**
         * 添加注解
         */
        for (AnnotationEnum lombokEnum : LOMBOK_ENUM) {
            topLevelClass.addImportedType(lombokEnum.importedType);
            topLevelClass.addAnnotation(lombokEnum.annotation);
        }

        topLevelClass.addImportedType(AnnotationEnum.TableName.importedType);
        topLevelClass.addAnnotation(AnnotationEnum.TableName.annotation + "(\"" + introspectedTable.getFullyQualifiedTable().getIntrospectedTableName() + "\")");


        /**
         * 添加 swagger API 配置注解
         */
        if (addSwagger) {
            String apiModelValue = introspectedTable.getRemarks() == null || "".equals(introspectedTable.getRemarks()) ?
                    introspectedTable.getFullyQualifiedTable().getIntrospectedTableName() : introspectedTable.getRemarks();
            topLevelClass.addImportedType(AnnotationEnum.API_MODEL.importedType);
            topLevelClass.addAnnotation(AnnotationEnum.API_MODEL.annotation + "(value = \"" + apiModelValue + "\")");
        }
        /**
         * 是否 集成父类
         */
        if (addRootClass) {
            topLevelClass.addImportedType(rootClass);

            if (addPkType) {
                List<IntrospectedColumn> pkColumn = introspectedTable.getPrimaryKeyColumns();
                String idJavaType = pkColumn != null && pkColumn.size() > 0 ? pkColumn.get(0).getFullyQualifiedJavaType().getShortName() : JavaTypeEnum.STRING.code;

                topLevelClass.setSuperClass(new FullyQualifiedJavaType(rootClass + "<" + idJavaType + ">"));
            } else {
                topLevelClass.setSuperClass(new FullyQualifiedJavaType(rootClass));
            }
        }
        return true;
    }

    @Override
    public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {

        String cloumn = messageUseColumnName || (introspectedColumn.getRemarks() == null || "".equals(introspectedColumn.getRemarks())) ?
                introspectedColumn.getJavaProperty() : introspectedColumn.getRemarks();


        if (introspectedColumn.isIdentity()) {
            topLevelClass.addImportedType(AnnotationEnum.TableId.importedType);
            field.addAnnotation(AnnotationEnum.TableId.annotation);
        }

        /**
         * 添加swagger API注解
         */
        if (addSwagger) {
            topLevelClass.addImportedType(AnnotationEnum.API_MODEL_PROPERTY.importedType);
            field.addAnnotation(AnnotationEnum.API_MODEL_PROPERTY.annotation + "(value = \"" + cloumn + "\")");
        }
        /**
         * 添加hibernate validate数据校验注解
         */
        if (addHibernateValidate) {
            setValidate(field, topLevelClass, introspectedColumn, cloumn);
        }
        return true;
    }

    private void setValidate(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, String cloumn) {
        if (JavaTypeEnum.STRING.code.equals(field.getType().getShortName())) {
            /**
             * 非主键的 String字段不为空 添加 @NotBlank 校验
             */
            if (!introspectedColumn.isNullable() && !introspectedColumn.isIdentity()) {
                topLevelClass.addImportedType(AnnotationEnum.NotBlank.importedType);
                field.addAnnotation(AnnotationEnum.NotBlank.annotation + "(message = \"" + cloumn + "不能为空\")");
            }
            topLevelClass.addImportedType(AnnotationEnum.Length.importedType);
            field.addAnnotation(AnnotationEnum.Length.annotation + "(max = " + introspectedColumn.getLength() + ",message = \"" + cloumn + "最长不能超过{max}个字符\")");

        } else {
            /**
             * 非主键的 其他字段不为空 添加 @NotNull 校验
             */
            if (!introspectedColumn.isNullable() && !introspectedColumn.isIdentity()) {
                topLevelClass.addImportedType(AnnotationEnum.NotNull.importedType);
                field.addAnnotation(AnnotationEnum.NotNull.annotation + "(message = \"" + cloumn + "不能为空\")");
            }
            /**
             * 数值类型判断最大值
             */
            if (JavaTypeEnum.DOUBLE.code.equals(field.getType().getShortName()) ||
                    JavaTypeEnum.INTEGER.code.equals(field.getType().getShortName()) ||
                    JavaTypeEnum.FLOAT.code.equals(field.getType().getShortName()) ||
                    JavaTypeEnum.SHORT.code.equals(field.getType().getShortName()) ||
                    JavaTypeEnum.LONG.code.equals(field.getType().getShortName())) {

            }
        }
    }


    /**
     * model不自动生成getter方法
     */
    @Override
    public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        return false;
    }

    /**
     * model不自动生成setter方法
     */
    @Override
    public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        return false;
    }
}
